/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package main.pso;

import java.util.logging.Level;
import java.util.logging.Logger;
import main.Centroid;
import main.DataVector;
import main.Particle;
import main.Util;
import main.Velocity;

/**
 *
 * @author Amigao
 */
public class StandartPSO extends PSO{
    public StandartPSO(String fileName){
        super(fileName);
    }

    /**
	 * Inicializa todas as particulas do enxame. Este m�todo for�a toda
	 * particula inicializada a estar pr�xima de um <br/>
	 * elemento do training set escolhido aleat�riamente.
	 *
	 * @param k
	 *            quantidade de controides de cada porticula.
	 * @param numberOfParticles
	 *            numero de particulas do enxame.
	 */
    @Override
    public void initializeParticles(int k, int numberOfParticles) {

		Particle particle = null;
		Centroid centroid = null;
		Velocity velocity = null;

		// para cada particula
		for (int i = 0; i < numberOfParticles; i++) {
			// inicializa a particula
			particle = new Particle(i, k);

			// para cada centroide na particula
			for (int j = 0; j < k; j++) {

				centroid = new Centroid(j, this.trainningSet.get(0)
						.getPosition().length);
				velocity = new Velocity(
						this.trainningSet.get(0).getPosition().length);
				// atribue a posi��o de um elemento aleat�tio do trainingSet ao
				// valor da posi��o do centr�ide
				centroid.setPosition(trainningSet.get(
						random.nextInt(trainningSet.size())).getPosition()
						.clone());

				for (int l = 0; l < centroid.getPosition().length; l++) {
					// o valor da velocidade � um valor aleat�rio em cada
					// particula.
					velocity.getVelocities()[l] = random.nextDouble();
                    //System.out.println(velocity.getVelocities()[l]);
				}

				particle.getCentroids()[j] = centroid;
				particle.getVelocities()[j] = velocity;

			}
			// adiciona a particula criada ao enxame
			this.swarm.add(particle);

		}

	}
    
    @Override
    public void execute(int k, int numberOfParticles, int numberOfIterations) {

		this.euclidianDistances = new double[k];

		this.initializeTrainingSet();

		this.initializeParticles(k, numberOfParticles);

		for (int i = 0; i <= numberOfIterations; i++) {
           
			for (Particle particle : this.swarm) {

				for (DataVector trainningData : trainningSet) {

					for (int j = 0; j < particle.getCentroids().length; j++) {
						this.euclidianDistances[j] = Util
								.calculateEuclidianDistance(trainningData,
										particle.getCentroids()[j]);
					}

					this.assignTrainningDataToNearestCentroid(trainningData,
							particle);

				}

				particle.calculateFitness();

				particle.updateLocalBestPosition();

			}

			this.updateGlobalBestPosition();

            double w = wMin + (i * ((wMax-wMin)/numberOfIterations));
			this.updateParticlesPositions(w);

                        //SOMENTE EXECUTAR COM DEBUG!!!
			//this.showChartParticlesMove();

		}

		this.evaluate(k, globalBestPosition);

	}

}
